package com.wsoft.oss.service.impl;

import cn.hutool.core.util.StrUtil;
import com.wsoft.constant.ConfigConstant;
import com.wsoft.constant.redis.RedisKeyConstant;
import com.wsoft.core.exception.Asserts;
import com.wsoft.core.service.CommonConfigService;
import com.wsoft.core.service.RedisService;
import com.wsoft.core.utils.LoginUserUtil;
import com.wsoft.core.vo.ConfigQuery;
import com.wsoft.oss.entity.OssFileEntity;
import com.wsoft.oss.enums.BucketNameEnum;
import com.wsoft.oss.enums.FileUpdateStatusEnum;
import com.wsoft.oss.manager.OssFileManager;
import com.wsoft.oss.query.FileInfoQuery;
import com.wsoft.oss.service.IOssFileService;
import com.wsoft.oss.service.IOssService;
import com.wsoft.oss.vo.FileUploadVO;
import com.wsoft.utils.RsaUtil;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Lazy;
import org.springframework.core.io.InputStreamResource;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @Author z001
 * @Date 2024/9/27 10:53
 */
@Service
public class OssFileServiceImpl implements IOssFileService {
    @Resource
    private OssFileManager ossFileManager;
    @Resource
    @Lazy
    private IOssService ossService;
    @Resource
    private RedisService redisService;
    @Value("${wsoft.rsa.privateKey}")
    private String privateKey;
    @Resource
    private CommonConfigService commonConfigService;

    /**
     * 根据id 返回文件二进制流
     * @param id
     * @return
     */
    @Override
    public Map<String,Object> get(Long id,Integer picType,String sessionId) throws Exception {
        OssFileEntity ossFile = ossFileManager.getById(id);
        //验证
        this.checkSessionId(sessionId,ossFile.getBucketName());

        InputStreamResource stream = ossService.getInputStream(ossFile,picType);

        Map<String,Object> map = new HashMap<>(2);
        map.put("fileName",ossFile.getName());
        map.put("stream",stream);
        return map;
    }

    @Override
    public  byte[] downloadPart(OssFileEntity fileEntity, Integer picType, String sessionId, String range,HttpServletResponse response) throws Exception {
        //验证
        this.checkSessionId(sessionId,fileEntity.getBucketName());
        return ossService.downloadPart(fileEntity,picType,range,response);
    }

    @Override
    public FileUploadVO checkFileByMd5(String md5, Integer fileSize) {
        Long fileMaxSize = getFileMaxSize();
        if(fileSize > fileMaxSize){
            //文件超出最大限制
            Asserts.fail("[oss.file.maximum.limit]");
        }
        FileUploadVO vo = new FileUploadVO();
        //redis中存在值,则代表续传
        Boolean b = redisService.hasKey(RedisKeyConstant.Oss.OSS_PART_INDEX + md5);
        if (b) {
            vo.setPartCountList(redisService.sMembers(RedisKeyConstant.Oss.OSS_PART_INDEX + md5));
            vo.setFileUpdateStatus(FileUpdateStatusEnum.UPLOADING.getType());
            return vo;
        }

        //mysql存在值 则已经上传过
        OssFileEntity ossFile = ossFileManager.getMd5(md5);
        if (ossFile != null) {
            vo.setFileUpdateStatus(FileUpdateStatusEnum.UPLOADED.getType());
        } else {
            vo.setFileUpdateStatus(FileUpdateStatusEnum.NOT_UPLOAD.getType());
        }
        return vo;
    }

    // ################################## 私有方法  ##################################

    /**
     * 验证sessionId 和 token 是否一致
     * @param sessionId
     * @param request
     */
    @Override
    public void checkSessionId(String sessionId,String bucketName){
        if(BucketNameEnum.LOGIN.getBucketName().equals(bucketName)){
            if(StrUtil.isBlank(sessionId)){
                Asserts.fail("[oss.illegal.request]");
            }
            //获取loginName
            String loginName = LoginUserUtil.getUserInfo().getLoginUserVO().getLoginName();
            //验证 sessionId 和 获取loginName 是否为同一人
            //解密sessionId
            String userName = RsaUtil.decryptDataOnJava(sessionId, privateKey);
            if(!userName.equals(loginName)){
                Asserts.fail("[oss.illegal.request]");
            }
        }
        if(BucketNameEnum.AUTHORITY.getBucketName().equals(bucketName)){
          // todo 待完善
        }
    }

    @Override
    public List<OssFileEntity> getFileInfo(FileInfoQuery query) {
        List<Long> idList = query.getIdList();
        Long fileId = idList.get(0);
        //取第一个id 校验session
        OssFileEntity fileEntity = ossFileManager.getById(fileId);
        checkSessionId(query.getSessionId(),fileEntity.getBucketName());
        return ossFileManager.listByIds(query.getIdList());
    }


    /**
     * 获取文件最大值
     * @return
     */
    @Override
    public Long getFileMaxSize(){
        ConfigQuery query = new ConfigQuery();
        query.setCode(ConfigConstant.OSS_CONFIG_FILE);
        Map<String, String> map = commonConfigService.getConfigValue(query);
        Object object = map.get(ConfigConstant.OSS_MAXIMUM_LIMIT);
        if(null == object){
            return null;
        }
        return Long.valueOf(object.toString());
    }
}
